﻿using System;
using System.Linq;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Services.Implementations;
using Services.Models;

namespace Socaloud.Broadcast {

    [HubName("matchTicker")]
    public class MatchHub : Hub {

        private readonly MatchTicker _matchTicker;

        public MatchHub()
            : this(MatchTicker.Instance) {

        }

        public MatchHub(MatchTicker matchTicker) {
            _matchTicker = matchTicker;
        }

        public MatchModel GetMatch(string id) {
            Groups.Add(Context.ConnectionId, id);
            return _matchTicker.GetMatch(id);
        }

    }

    public class MatchTicker {

        private readonly static Lazy<MatchTicker> _instance = new Lazy<MatchTicker>(
           () => new MatchTicker(GlobalHost.ConnectionManager.GetHubContext<MatchHub>().Clients));

        private readonly object _updateLock = new object();
        private volatile bool _updating = false;

        public static MatchTicker Instance {
            get {
                return _instance.Value;
            }
        }

        private IHubConnectionContext Clients {
            get;
            set;
        }

        private Timer _timer;

        private static ConcurrentDictionary<string, MatchModel> _matches = new ConcurrentDictionary<string, MatchModel>();

        public MatchTicker(IHubConnectionContext clients) {
            Clients = clients;

            var matches = new XmlSoccerService().GetMatches().ToList();
            matches.ForEach(x => _matches.TryAdd(x.Id, x));
            var updateInterval = TimeSpan.FromMilliseconds(2500);
            _timer = new Timer(UpdateMatch, null, updateInterval, updateInterval);
        }

        private void UpdateMatch(object state) {

            lock(_updateLock) {

                if(!_updating) {

                    _updating = true;

                    MatchModel temp;
                    var latest = new XmlSoccerService().GetMatches();
                    foreach(var item in latest) {

                        var match = _matches.Values.FirstOrDefault(x => x.Id == item.Id);
                        if(match != null) {
                            if(!item.Equals(match)) {
                                Clients.Group(item.Id).updateMatch(item);
                            }
                            _matches.TryRemove(match.Id, out temp);
                        }

                        _matches.TryAdd(item.Id, item);
                    }

                    _updating = false;
                }
            }
        }

        public MatchModel GetMatch(string id) {
            if(string.IsNullOrEmpty(id)) {
                return null;
            }
            return _matches.Values.FirstOrDefault(x => x.Id == id);
        }
    }

}